home *** CD-ROM | disk | FTP | other *** search
/ No Fragments Archive 12: Textmags & Docs / nf_archive_12.iso / MAGS / SOURCES / ATARI_SRC.ZIP / atari source / HDX_BACK / HDX302.ST / STEPART.C < prev    next >
Encoding:
C/C++ Source or Header  |  2001-02-09  |  45.2 KB  |  1,773 lines

  1. /*
  2.  * Partition editing and picking.
  3.  *
  4.  * 09-Dec-87    ml.    Added pheader() to take care of placing partition
  5.  *            headers at good sectors.
  6.  * 14-Jan-88    ml.    Added chkpart() to make sure partition scheme does
  7.  *            not map pass end of device.
  8.  * 02-Dec-88     jye. Change and add codes so that can be used for MS-DOS
  9.  *
  10.  * 12-Dec-89    jye. Fixed a bug in stuffamt() so that correctly show three
  11.  *                digits or more in the partitioning deialog box.
  12.  */
  13.  
  14. #include "obdefs.h"
  15. #include "gemdefs.h"
  16. #include "osbind.h"
  17. #include "mydefs.h"
  18. #include "part.h"
  19. #include "bsl.h"
  20. #include "hdx.h"
  21. #include "addr.h"
  22. #include "error.h"
  23. #include "ipart.h"
  24.  
  25. #define ROLL1 1            /* move the bar one step */
  26. #define ROLL4 4            /* move the bar four steps */
  27. #define NULL 0L            /* the nill pointer */
  28.  
  29. extern int wdesk;
  30. extern int hdesk;
  31. extern long gbslsiz();
  32. extern long getdsiz();
  33. extern long bslsiz;
  34. extern SECTOR badbuf[];        /* bad sectors buffer */
  35. extern long ostack;
  36. extern long sptrk;                /* sector per track */
  37. extern long disksiz;            /* size of disk in blocks */
  38. extern int yesscan;            /* the flag for the func. IBMGPART use */
  39. extern int npart;            /* number of partitions */
  40. extern int ext;            /* the index that point to the extended partition */
  41. extern int extend;        /* the index that point to the end of extended */
  42. extern char ttscsi;        /* 1: SCSI bus drive */
  43.  
  44.  
  45. /*
  46.  * Global variables these routines communicate with
  47.  *
  48.  */
  49. static PART *pinfo;        /* -> partition block */
  50. static int totcyl;        /* total # of cylinder */
  51. static long sizleft;    /* size of unused disk in blocks */
  52. static long extleft;    /* size of unused extended partition in blocks */
  53. static int formw, formh;
  54. static int lx, ly, sx, sy;
  55. static int ok2draw;        /* 0: don't draw PARTPNL boxes */
  56. static char partnames[NAMSIZ];    /* partition name buffer */
  57. static int menuflg;        /* negative: never called partmenu */
  58. static int pnlflg;        /* 1: partition scheme comes from panel */
  59. static int along;        /* 1: will not redraw and clean the box */
  60. static int first;        /* flag for add bad and good sectors only one time */
  61. long sumsiz;            /* the sum of bytes of root sectors */
  62. int tolpart;            /* the total of number partitions */
  63. int epty;                /* the y-coordinate of the moving bar */
  64. int uplim;                /* index of dialog box */
  65. int lowlim;                /* index of dialog box */
  66. int restept;            /* 1: rest the moving bar to initial place */
  67. DPART *headptr;            /* the head pointer of structure */
  68. long ratio, bps;
  69. long nill = (long)NULL;
  70. int prevnpart;            /* former number of partitions */
  71.  
  72.  
  73. /*
  74.  * Figure out partition information;
  75.  *    return OK if xpinfo[] is filled-in,
  76.  *         ERROR on [CANCEL] or something.
  77.  */
  78. sfigpart(bs, dev, rpinfo)
  79.  
  80. char *bs;
  81. int dev;
  82. PART **rpinfo;
  83.  
  84. {
  85.     int ret;
  86.  
  87.     lowlim = 0;
  88.     uplim = 4;
  89.     first = 0;
  90.     along = 0;        /* will redraw and clean the box */
  91.     restept = 0;
  92.  
  93.     /*  Get partition information from disk's root block. */
  94.     if ((ret = getroot(dev, bs, (SECTOR)0)) != 0) {
  95.         if (tsterr(ret) != OK)
  96.             err(rootread);
  97.         return ERROR;
  98.     }
  99.     yesscan = 0;
  100.     
  101.     /* get bad sectors list size */
  102.     if ((bslsiz = gbslsiz(dev)) == 0L) {    /* no bsl */
  103.         return err(oldfmt);
  104.     } else if (bslsiz < 0L) {            /* error occurred */
  105.         if (bslsiz == ERROR)            /* read error */
  106.             err(rootread);
  107.         return ERROR;                /* medium changed error */
  108.     }
  109.  
  110.       if ((ret = chkroot(dev, bs)) == -3)    { /*don't have to show the alert box */ 
  111.         return ERROR;
  112.     } else if (ret != OK)    {
  113.            return err(cruptfmt);
  114.     }
  115.  
  116.     disksiz = ((RSECT *)(bs + 0x200 - sizeof(RSECT)))->hd_siz;
  117.     if (stgpart(dev, bs, (PART *)&pinfo) == ERROR)    {
  118.         if (pinfo > 0) Mfree(pinfo);
  119.         return ERROR;
  120.     }
  121.     if (ext != NO_EXT)    sortpart(pinfo, USER_ED);
  122.  
  123.     /* put partition infomations into the dynamic structure */
  124.     if (part2dpart(npart) == ERROR)        {
  125.         return ERROR;
  126.     }
  127.     menuflg = -1;    /* first time through */
  128.     restept = 1;
  129.     prevnpart = npart;
  130.     for (;;)
  131.     {
  132.     switch (sdoscrbar())
  133.     {
  134.         case SPMENU:            /* chose from menu */
  135.             switch (spartmenu())
  136.             {
  137.                 case PPOK:        *rpinfo = pinfo;
  138.                                 return OK;    /* [OK] */
  139.                 default:
  140.                 case PPCN:        if (pinfo > 0) Mfree(pinfo);
  141.                                 if (headptr > 0) free(headptr);
  142.                                 return BAILOUT;    /* [CANCEL] */
  143.                 case PPEDIT:    restept = 1; 
  144.                                 lowlim = 0;
  145.                                 uplim = 4;
  146.                                 break;        /* continue and edit */
  147.             }
  148.             break;
  149.  
  150.         case EXPERT:    along = 0;
  151.                         lowlim = 0;
  152.                         uplim = 4;
  153.                         restept = 1;
  154.                         ext = 1;        /* set default to 1 */
  155.                         extend = npart-2;
  156.                         switch (doexpert())    {
  157.                             case NOSEL:        if (pinfo > 0)    {
  158.                                                 inipart(pinfo, prevnpart);
  159.                                                 Mfree(pinfo);
  160.                                             }
  161.                                             if (headptr > 0) free(headptr);
  162.                                             return BAILOUT;    /* [CANCEL] */
  163.                             case SELOK:    pnlflg = 1;    
  164.                                         if (pinfo > 0)    {
  165.                                             inipart(pinfo, prevnpart);
  166.                                             Mfree(pinfo);
  167.                                         }
  168.                                         if (dpart2part(ext) == ERROR) {
  169.                                             if (headptr > 0) free(headptr);
  170.                                             if (pinfo > 0) Mfree(pinfo);
  171.                                                 return ERROR;
  172.                                         }
  173.                                         *rpinfo = pinfo;
  174.                                         return OK;
  175.                             default:
  176.                             case TOEDIT: break;
  177.                         }
  178.  
  179.         case SCRUP:      break;
  180.         case SCRDN:      break;
  181.         case SCRBAR:      break;
  182.         case SCREPT:      break;
  183.         case SUNDO:      break;
  184.  
  185.         default:
  186.         case SEPOK:    *rpinfo = pinfo;
  187.                     return OK;
  188.         case SEPCN: if (pinfo > 0) Mfree(pinfo);
  189.                     if (headptr > 0) free(headptr);
  190.                     return BAILOUT;
  191.     }
  192.     }
  193. }
  194.  
  195. int objnums[] = { SPARTNM0, SPARTNM1, SPARTNM2, SPARTNM3};
  196. int objups[] = {SEP0UP, SEP1UP, SEP2UP, SEP3UP};
  197. int objdns[] = {SEP0DN, SEP1DN, SEP2DN, SEP3DN};
  198. int objsizs[] = {SEP0SIZ, SEP1SIZ, SEP2SIZ, SEP3SIZ};
  199. char *sizstr[6] = {"1000.0Mb0", "1000.0Mb0", "1000.0Mb0", "1000.0Mb0", 
  200.                    "1000.0Mb0", " 999 partition(s)"};
  201. char *numstr[4] = {"#999", "#999", "#999", "#999"};
  202.  
  203.  
  204. int objnum[] = { PART1, PART2, PART3, PART4, PARTX, PARTY, PARTZ};
  205. char *xsizstr[7] = {"1000.0Mb0", "1000.0Mb0", "1000.0Mb0", "1000.0Mb0", 
  206.                    "1000.0Mb0", "1000.0Mb0", "1000.0Mb0"};
  207. int objsiz[] = {PART1MB, PART2MB, PART3MB, PART4MB, PARTXMB, PARTYMB, PARTZMB};
  208. char *xnumstr[7] = {"#999", "#999", "#999", "#999", "#999", "#999", "#999"};
  209. int objsel[] = { SELECT1, SELECT2, SELECT3, SELECT4, SELECT5, SELECT6};
  210. char *selstr[6] = {"from #2 to #99", "from #2 to #99", "from #2 to #99", 
  211.                     "from #3 to #99", "from #3 to #99", "from #4 to #99" };
  212. doexpert()
  213. {
  214.  
  215.     int i, lastpno, pno;
  216.     int run = 1;
  217.     int erase = 0;
  218.     int but;
  219.  
  220.     ok2draw = 0;
  221.  
  222.  
  223.     exppnl[TOEDIT].ob_state = NORMAL;
  224.     exppnl[NOSEL].ob_state = NORMAL;
  225.     exppnl[SELOK].ob_state = NORMAL;
  226.  
  227.     drawsel(2, npart-2, 0, exppnl);
  228.     drawsel(2, npart-1, 1, exppnl);
  229.     drawsel(2, npart, 2, exppnl);
  230.     drawsel(3, npart-1, 3, exppnl);
  231.     drawsel(3, npart, 4, exppnl);
  232.     drawsel(4, npart, 5, exppnl);
  233.  
  234.  
  235.     for (i = 0; i < 7; i++)        {
  236.         if (npart > 7)    {
  237.             if (i > 3)    {
  238.                 if (i == 4)
  239.                     lastpno = npart - i + 1;
  240.                 drawpart(i, lastpno++, exppnl);
  241.             } else {
  242.                 drawpart(i, i, exppnl);
  243.             }
  244.         } else if (npart == 5)    {
  245.             if (i > 4)    {
  246.                 pno = -1;
  247.                 drawpart(i, pno, exppnl);
  248.             } else {
  249.                 drawpart(i, i, exppnl);
  250.             }
  251.         } else if (npart == 6)    {
  252.             if (i > 5)    {
  253.                 pno = -1;
  254.                 drawpart(i, pno, exppnl);
  255.             } else {
  256.                 drawpart(i, i, exppnl);
  257.             }
  258.         } else {
  259.             drawpart(i, i, exppnl);
  260.         }
  261.     }
  262.  
  263.     /* set the default selected */
  264.     exppnl[SELECT1].ob_state = NORMAL | SELECTED;
  265.     exppnl[SELECT2].ob_state = NORMAL;
  266.     exppnl[SELECT3].ob_state = NORMAL;
  267.     exppnl[SELECT4].ob_state = NORMAL;
  268.     exppnl[SELECT5].ob_state = NORMAL;
  269.     exppnl[SELECT6].ob_state = NORMAL;
  270.     turnexton(1, npart-2);
  271.  
  272.     ARROW_MOUSE;
  273.     dsplymsg(exppnl);
  274.  
  275.     ++ok2draw;
  276.     while (run)        {
  277.         switch((but = form_do(exppnl, -1)))        {
  278.             case TOEDIT:    run = 0; 
  279.                             break;
  280.             case NOSEL:        run = 0;
  281.                             erase = 1;
  282.                             break;
  283.             case SELOK:        run = 0;
  284.                             erase = 1;
  285.                             break;
  286.             case SELECT1:    ext = 1;
  287.                             extend = npart - 2;
  288.                             turnexton(1, npart-2);
  289.                             break;
  290.             case SELECT2:    ext = 1;
  291.                             extend = npart - 1;
  292.                             turnexton(1, npart-1);
  293.                             break;
  294.             case SELECT3:    ext = 1;
  295.                             extend = npart;
  296.                             turnexton(1, npart);
  297.                             break;
  298.             case SELECT4:    ext = 2;
  299.                             extend = npart - 1;
  300.                             turnexton(2, npart-1);
  301.                             break;
  302.             case SELECT5:    ext = 2;
  303.                             extend = npart;
  304.                             turnexton(2, npart);
  305.                             break;
  306.             case SELECT6:    ext = 3;
  307.                             extend = npart;
  308.                             turnexton(3, npart);
  309.                             break;
  310.         }
  311.     }
  312.     if (erase)    {
  313.         erasemsg();
  314.         BEE_MOUSE;
  315.     }
  316.     return but;
  317. }
  318.  
  319. turnexton(stnum, endnum)
  320. int stnum;        /* the number that start to turn on the extended partition */
  321. int endnum;        /* the number that end to turn on the extended partition */
  322. {
  323.     int i;
  324.  
  325.     if (npart > 7)    {
  326.         endnum = 7 - (npart - endnum);
  327.     }
  328.     for (i = 0; i < 7; i++)    {
  329.         exppnl[objsiz[i]].ob_state = NORMAL;
  330.         if ((i >= stnum) && (i < endnum))    {
  331.             exppnl[objsiz[i]].ob_state |= SELECTED;
  332.         }
  333.         if (ok2draw)    {
  334.             objc_draw(exppnl, objsiz[i], MAX_DEPTH, 0, 0, wdesk, hdesk);
  335.         }
  336.  
  337.     }
  338.     ok2draw++;
  339. }
  340.  
  341.  
  342.  
  343.  
  344. drawsel(stnum, tonum, num, pnl)
  345. int stnum;        /* the first extended partition number */
  346. int tonum;        /* the last extended partition number */
  347. int num;        /* the number of selected extended partition scheme */
  348. OBJECT *pnl;
  349. {
  350.  
  351.     /* set the select range in the dialog box */
  352.     calextnum(stnum, tonum, selstr[num]);
  353.     (pnl[objsel[num]].ob_spec)->te_ptext = selstr[num];
  354.     if (ok2draw)    {
  355.         objc_draw(pnl, objsel[num], MAX_DEPTH, 0, 0, wdesk, hdesk);
  356.     }
  357. }
  358.  
  359.  
  360. drawpart(num, pno, pnl)
  361. int num;        /* the number of selected extended partition scheme */
  362. int pno;        /* the partition number */
  363. OBJECT *pnl;
  364. {
  365.     DPART *pinfo, *addr();
  366.  
  367.     if (pno == NO_EXT)    { /* not exists */
  368.         pnl[objsiz[num]].ob_spec = "Unused";
  369.         pnl[objsiz[num]].ob_state = NORMAL;
  370.         pnl[objsiz[num]].ob_flags = TOUCHEXIT;
  371.         (pnl[objnum[num]].ob_spec)->te_ptext = "     ";
  372.     } else {
  373.         pinfo = addr(pno);
  374.         stuffamt(pinfo->siz, xsizstr[num]);
  375.         pnl[objsiz[num]].ob_spec = xsizstr[num];
  376.         pnl[objsiz[num]].ob_state = NORMAL;
  377.         pnl[objsiz[num]].ob_flags = TOUCHEXIT;
  378.  
  379.         stpartnum(pno+1, xnumstr[num]);
  380.         (pnl[objnum[num]].ob_spec)->te_ptext = xnumstr[num];
  381.     }
  382.     if (ok2draw)    {
  383.         objc_draw(pnl, objsiz[num], MAX_DEPTH, 0, 0, wdesk, hdesk);
  384.         objc_draw(pnl, objnum[num], MAX_DEPTH, 0, 0, wdesk, hdesk);
  385.     }
  386.  
  387. }
  388.  
  389. sdoscrbar()
  390.  
  391. {
  392.  
  393.     int i, j, but, step;
  394.     int xrun = 1;
  395.     long usesiz;
  396.     DPART *temptr, *addr();
  397.  
  398.     ok2draw = (along) ? 1 : 0;
  399.  
  400.     /* set form for first display */
  401.     scrpnl[SEPOK].ob_state = NORMAL;
  402.     scrpnl[SEPCN].ob_state = NORMAL;
  403.     scrpnl[SPMENU].ob_state = NORMAL;
  404.     scrpnl[SUNDO].ob_state = NORMAL;
  405.  
  406.     if (!first++)    {    /* initially ST partition */
  407.         temptr = headptr;
  408.         for (i = 0; i < npart; i++)    {
  409.             if ((temptr->flg & P_EXISTS) && 
  410.                 (!((temptr->next)->flg & P_EXISTS)))    {
  411.                 temptr->siz += bslsiz + 1; /* add sacrificed space back */
  412.             }
  413.             temptr = temptr->next;
  414.         }
  415.     }
  416.  
  417.     for (i = -1; i < 4; ++i)
  418.          sepadj(0L, i, scrpnl);
  419.     if (restept)    {
  420.         scrpnl[SCREPT].ob_y = 0;
  421.         restept = 0;
  422.     }
  423.     if (!along)        {
  424.         ARROW_MOUSE;
  425.         dsplymsg(scrpnl);
  426.     }
  427.  
  428.     /*
  429.      * Edit the thing;
  430.      * canonical event-driven switch().
  431.      */
  432.     ++ok2draw;
  433.     while (xrun)     {
  434.     along = 0;
  435.     if (npart > 4)    {
  436.         scrpnl[EXPERT].ob_state = NORMAL;
  437.         scrpnl[EXPERT].ob_flags = TOUCHEXIT;
  438.     } else {
  439.         scrpnl[EXPERT].ob_state = DISABLED;
  440.         scrpnl[EXPERT].ob_flags = NONE;
  441.     }
  442.     objc_draw(scrpnl, EXPERT, MAX_DEPTH, 0, 0, wdesk, hdesk);
  443.  
  444.     switch ((but = form_do(scrpnl, -1)))
  445.     {
  446.     case SEPOK:    pnlflg = 1;
  447.                 if (pinfo > 0L)    {
  448.                     inipart(pinfo,prevnpart);
  449.                     Mfree(pinfo);
  450.                 }
  451.                 ext = 1;        /* set the default extended partition */
  452.                 extend = npart - 2;
  453.                 if (dpart2part(ext) == ERROR) return ERROR;
  454.                 xrun = 0;
  455.                 break;
  456.     case SEPCN:    xrun = 0;            /* return */
  457.                     break;
  458.     case EXPERT: if (npart > 4)        {
  459.                     xrun = 0;
  460.                     break;
  461.                  } else {
  462.                      xrun = 1;
  463.                     break;
  464.                  }
  465.     case SCRBAR: if (sdoscrupdn(ROLL4) == ERROR) return ERROR;
  466.                     xrun = 0;
  467.                     break;
  468.     case SCRUP:  if (sdoscrupdn(ROLL1) == ERROR) return ERROR;
  469.                 xrun = 0;
  470.                 break;
  471.     case SCRDN:  if (sdoscrupdn(ROLL1) == ERROR) return ERROR;
  472.                 xrun = 0;
  473.                 break;
  474.     case SCREPT: if (sdoslidebox(scrpnl) == ERROR) return ERROR;
  475.                 xrun = 0;
  476.                 break;
  477.     case SPMENU:    xrun = 0;
  478.                     break;
  479.  
  480.     case SUNDO:     /* restore the starting parameters */
  481.                 lowlim = 0;
  482.                 uplim = 4;
  483.                 if (part2dpart(prevnpart) == ERROR)    return ERROR;
  484.                 for (i = -1; i < NPARTS; ++i)
  485.                     sepadj(0L, i, scrpnl);
  486.                 npart = prevnpart;
  487.                 scrpnl[SCREPT].ob_y = 0;
  488.                 objc_draw(scrpnl, SCRBAR, MAX_DEPTH, 0, 0, wdesk, hdesk);
  489.                 break;
  490.  
  491.     case SEP0SIZ:xrun = septoggle(0, scrpnl);    break;
  492.     case SEP0UP:    sepadj(MEGABYTE, 0, scrpnl);    break;
  493.     case SEP0DN:    sepadj(-MEGABYTE, 0, scrpnl);    break;
  494.  
  495.     case SEP1SIZ:xrun = septoggle(1, scrpnl);    break;
  496.     case SEP1UP:    sepadj(MEGABYTE, 1, scrpnl);    break;
  497.     case SEP1DN:    sepadj(-MEGABYTE, 1, scrpnl);    break;
  498.  
  499.     case SEP2SIZ:xrun = septoggle(2, scrpnl);    break;
  500.     case SEP2UP:    sepadj(MEGABYTE, 2, scrpnl);    break;
  501.     case SEP2DN:    sepadj(-MEGABYTE, 2, scrpnl);    break;
  502.  
  503.     case SEP3SIZ:xrun = septoggle(3, scrpnl);    break;
  504.     case SEP3UP:    sepadj(MEGABYTE, 3, scrpnl);    break;
  505.     case SEP3DN:    sepadj(-MEGABYTE, 3, scrpnl);    break;
  506.       }
  507.   }
  508.  
  509.  
  510.     /*
  511.      * Draw shrinking box and cleanup the screen;
  512.      * return thing that caused our exit.
  513.      */
  514.     if (!along)    {
  515.         erasemsg();
  516.         BEE_MOUSE;
  517.     }
  518.     return but;
  519. }
  520.  
  521.  
  522.  
  523.  
  524. /* 
  525.  * conver the partition number for the dialog box to the string .
  526.  *
  527.  */
  528.  
  529. calextnum(stnum, tonum, str)
  530.  
  531. int stnum,tonum;
  532. char *str;
  533.  
  534. {
  535.     int  i = 0;
  536.     int addspace = 0;
  537.     char tem[10];
  538.  
  539.     /* set the partition number header */
  540.     *str++ = 'f';
  541.     *str++ = 'r';
  542.     *str++ = 'o';
  543.     *str++ = 'm';
  544.     *str++ = ' ';
  545.     *str++ = '#';
  546.     *str++ = stnum % 10 + '0';
  547.     *str++ = ' ';
  548.     *str++ = 't';
  549.     *str++ = 'o';
  550.     *str++ = ' ';
  551.     *str++ = '#';
  552.     /* conver the integer to ASCII */
  553.     do    {    /* generate digits in reverse order */
  554.         tem[i++] = tonum % 10 + '0';    /* get next digits */
  555.     } while ((tonum /= 10) > 0);        /* delete it */
  556.  
  557.     if (i == 1)    {
  558.         addspace = 1;
  559.     }
  560.     for (; i > 0; )    { /* reverse string 'str' in place */
  561.         *str++ = tem[--i];
  562.     }
  563.     if (addspace)    *str++ = ' ';
  564.        *str = '\0';
  565. }
  566.  
  567.  
  568. sdoscrupdn(roll)
  569. int roll;
  570.  
  571. {
  572.      int gr_mkmx, gr_mkmy;
  573.     int gr_mkmstate, gr_mkkstate;
  574.     int barht, barx, bary;
  575.     int eptx, eptht;
  576.  
  577.     along = 1;
  578.     barht = scrpnl[SCRBAR].ob_height;
  579.     eptht = scrpnl[SCREPT].ob_height;
  580.     graf_mkstate(&gr_mkmx, &gr_mkmy, &gr_mkmstate, &gr_mkkstate);
  581.     objc_offset(scrpnl, SCREPT, &eptx, &epty);
  582.     objc_offset(scrpnl, SCRBAR, &barx, &bary);
  583.     /* check which part of bar was clicked */
  584.     if (gr_mkmy > (epty+eptht))    {    /* low part of bar was clicked */
  585.         if (roll == ROLL4)    {
  586.             if ((eptht > (bary+barht-epty-eptht)) || (lowlim == 20))    {
  587.                 scrpnl[SCREPT].ob_y = barht - eptht;
  588.             } else {
  589.                 scrpnl[SCREPT].ob_y += eptht;
  590.             }
  591.             lowlim += 4;
  592.             if ((lowlim + 4) > uplim) uplim += 4;
  593.             if (uplim > npart)    {
  594.                 if (creatmem(ROLL4) == ERROR)    {
  595.                     return ERROR;
  596.                 }
  597.             }
  598.         } else {
  599.             if ((eptht > ((bary+barht-epty-eptht) * 4)) || (lowlim == 23))    {
  600.                 scrpnl[SCREPT].ob_y = barht - eptht;
  601.             } else {
  602.                 scrpnl[SCREPT].ob_y += eptht / 4;
  603.             }
  604.             lowlim++;
  605.             if ((lowlim + 4) > uplim)      uplim++;
  606.             if (uplim > npart)    {
  607.                 if (creatmem(ROLL4) == ERROR)    {
  608.                     return ERROR;
  609.                 }
  610.             }
  611.         }
  612.     } else if (gr_mkmy < epty)    {    /* upper part of bar was clicked */
  613.         if (roll == ROLL4)    {
  614.             if ((eptht > (epty - bary)) || (lowlim <= 4))    {
  615.                 scrpnl[SCREPT].ob_y = 0;
  616.                 lowlim = 0;
  617.             } else {
  618.                 scrpnl[SCREPT].ob_y -= eptht;
  619.                 lowlim -= 4;
  620.             }
  621.         } else {
  622.             if ((eptht > ((epty - bary) * 4)) || (lowlim == 1))    {
  623.                 scrpnl[SCREPT].ob_y = 0;
  624.             } else {
  625.                 scrpnl[SCREPT].ob_y -= eptht / 4;
  626.             }
  627.             if (lowlim)     {
  628.                 lowlim--;
  629.             }
  630.         }
  631.     }
  632.     objc_draw(scrpnl,SCRBAR, MAX_DEPTH, 0, 0, wdesk, hdesk);
  633. }
  634.  
  635.  
  636. #define WHITEBAR 24        /* when the white bar on the bottom, the */
  637.                         /* 'lowlim' will equal to 24 */
  638. sdoslidebox(tree)
  639.  
  640. OBJECT *tree;
  641.  
  642. {
  643.     int gr_wreturn, eptatmax;
  644.     int numofmem;            /*   # of memories to be allocated */
  645.  
  646.     along = 1;
  647.     eptatmax = tree[SCRBAR].ob_height - tree[SCREPT].ob_height;
  648.     gr_wreturn = graf_slidebox(tree, SCRBAR, SCREPT, 1);
  649.     lowlim = (WHITEBAR * gr_wreturn) / 1000;
  650.     if ((lowlim >= uplim) || ((lowlim + 4) > uplim))     {
  651.         uplim = lowlim + 4;
  652.         if (uplim > npart)    {
  653.             numofmem = uplim - npart;
  654.             if (creatmem(numofmem) == ERROR)    {
  655.                 return ERROR;
  656.             }
  657.         }
  658.     }
  659.     /*
  660.     tree[SCREPT].ob_y = (eptatmax * gr_wreturn) / 1000;
  661.     */
  662.     tree[SCREPT].ob_y = (eptatmax * lowlim ) / 24;
  663.     objc_draw(tree, SCRBAR, MAX_DEPTH, 0, 0, wdesk, hdesk);
  664. }
  665.  
  666.  
  667.  
  668. /*
  669.  * Toggle partition in/out of existence.
  670.  */
  671. septoggle(n, pnl)
  672. int n;
  673. OBJECT *pnl;
  674. {
  675.     int i; 
  676.     DPART *pinfo, *ppinfo, *npinfo, *addr();
  677.     /*
  678.      * Toggle existance flag,
  679.      * enforce minimum partition size.
  680.      */
  681.     i = n + lowlim;
  682.     pinfo = addr(i);    /* return the structure pointer */
  683.     ppinfo = addr(i-1);    /* return the previous structure pointer */
  684.     npinfo = addr(i+1);    /* return the next structure pointer */
  685.     if ((!(pinfo->flg & P_EXISTS)) && (pinfo->siz) && (ppinfo)
  686.                             && (ppinfo->flg & P_EXISTS)){
  687.         if (maxmsg(pnl,i,tolpart) == NOMAX) return ON;
  688.         pinfo->flg = P_EXISTS;
  689.         sepadj(0L, n, pnl);
  690.     } else if (((pinfo->flg ^= P_EXISTS) & P_EXISTS) 
  691.           && !pinfo->siz) {
  692.         /* make extended partition continue */
  693.         if (!i || ((ppinfo) && (ppinfo->flg & P_EXISTS)))        {
  694.             if (maxmsg(pnl,i,tolpart) == NOMAX) return ON;
  695.             sepadj(MEGABYTE, n, pnl);
  696.         } else {
  697.             sepadj(0L, n, pnl);
  698.         }
  699.     } else if ((!lowlim) && (!i)&&(!(npinfo->flg & P_EXISTS)))    {
  700.         sepadj(0L, n, pnl);
  701.     } else if ((!lowlim) && (!i)&&(pinfo->flg & P_EXISTS))    {
  702.         sepadj(0L, n, pnl);
  703.     } else {             /* do nothing, turn it back to the initial state */
  704.         pinfo->flg ^= P_EXISTS;
  705.         if ((pinfo->flg & P_EXISTS) && (!(npinfo->flg & P_EXISTS))) {
  706.               pinfo->flg ^= P_EXISTS;
  707.             sepadj(0L, n, pnl);
  708.         }
  709.     }
  710.     sepadj(0L, -1, pnl);            /* update #left field */
  711.     return YES;
  712. }
  713.     
  714.  
  715. /*
  716.  * Adjust partition `pno' size by `amt';
  717.  * if `pno' is -1, just recompute and update disk space left indicator.
  718.  *
  719.  * A partition of size zero is disabled.
  720.  */
  721.  
  722. #define HALFMEGA 1024L
  723.  
  724. sepadj(amt, pno, pnl)
  725. long amt;
  726. int pno;
  727. OBJECT *pnl;
  728. {
  729.     int i;
  730.     long siz;
  731.     long sizhas;     /* disk size left in sectors */
  732.     long totsiz = 0;
  733.     DPART *pinfo, *npinfo, *addr();
  734.  
  735.     if (pno < 0) 
  736.         goto fixleft;
  737.     pno += lowlim;
  738.  
  739.     pinfo = headptr;
  740.     /* compute total used */
  741.     while (pinfo->flg & P_EXISTS)    {
  742.             totsiz += pinfo->siz;
  743.             pinfo = pinfo->next;
  744.     }
  745.     pinfo = addr(pno);
  746.     npinfo = addr(pno+1);
  747.     sizhas = disksiz;
  748.  
  749.     /*
  750.      * If total partition size exceeds the disk's
  751.      * capacity, reduce `amt' accordingly.
  752.      */
  753.     if (amt >= 0 && totsiz + amt > sizhas)
  754.     amt = sizhas - totsiz;
  755.  
  756.     if (amt > 0) {
  757.     /*
  758.      * Enforce maximum partition size.
  759.      */
  760.     siz = sizhas - totsiz;            /* siz = #free */
  761.     if (amt > siz) amt = siz;        /* ensure amt <= siz */
  762.     if (pinfo->siz + amt > sizhas)    /* ensure partition not */
  763.         amt = sizhas - pinfo->siz;    /* too big */
  764.  
  765.     /* check the partition size that can't over 256Mb (8K bytes per sect) */
  766.     /* for the reason of hardware                                           */
  767.     if ((pinfo->siz + amt) > 256 * 2048)    {
  768.         form_alert(1, maxpsize);
  769.         return OK;
  770.     }
  771.     pinfo->siz += amt;        /* bump partition size */
  772.     pinfo->flg = P_EXISTS;
  773.     } else if (amt < 0) {
  774.     amt = -amt;
  775.     if (pinfo->siz > amt) {        /* reduce partition size */
  776.         pinfo->siz -= amt;
  777.         if ((pinfo->siz < HALFMEGA) && (npinfo->flg & P_EXISTS))
  778.             pinfo->siz = amt;
  779.     } else if ((pinfo->siz <= amt) &&
  780.                 (!(npinfo->flg & P_EXISTS)))    {
  781.         /* reduce partition size */
  782.         pinfo->siz = 0L;
  783.     } 
  784.   }
  785.  
  786.     /*
  787.      * Enforce minimum partition size of half mega byte 
  788.      */
  789.     if (pinfo->siz < HALFMEGA)
  790.     pinfo->siz = 0L;
  791.  
  792.     /*
  793.      * Disable partitions of zero size
  794.      */
  795.     if (!pinfo->siz)    {
  796.         pinfo->flg &= ~P_EXISTS;
  797.     }
  798.  
  799.     /*
  800.      * Redraw the thing;
  801.      * if partition is disabled, shadow it and disable UP/DOWN buttons;
  802.      * otherwise setup the buttons, setup size string, and so on...
  803.      */
  804.     pno -= lowlim;
  805.     if (!(pinfo->flg & P_EXISTS)) {
  806.         pnl[objsizs[pno]].ob_spec = "Unused";
  807.         pnl[objsizs[pno]].ob_state = NORMAL;
  808.         pnl[objsizs[pno]].ob_flags = TOUCHEXIT;
  809.  
  810.         pnl[objups[pno]].ob_state = DISABLED;
  811.         pnl[objups[pno]].ob_flags = NONE;
  812.  
  813.         pnl[objdns[pno]].ob_state = DISABLED;
  814.         pnl[objdns[pno]].ob_flags = NONE;
  815.     } else {
  816.         stuffamt(pinfo->siz, sizstr[pno]);
  817.         pnl[objsizs[pno]].ob_spec = sizstr[pno];
  818.         pnl[objsizs[pno]].ob_state = NORMAL;
  819.         pnl[objsizs[pno]].ob_flags = TOUCHEXIT;
  820.  
  821.         pnl[objups[pno]].ob_state = NORMAL;
  822.         pnl[objups[pno]].ob_flags = TOUCHEXIT;
  823.  
  824.         pnl[objdns[pno]].ob_state = NORMAL;
  825.         pnl[objdns[pno]].ob_flags = TOUCHEXIT;
  826.     }
  827.  
  828.     /* set the partition numbers in the dialog box */
  829.     stpartnum(lowlim+pno+1, numstr[pno]);
  830.     (pnl[objnums[pno]].ob_spec)->te_ptext = numstr[pno];
  831.  
  832.     if (ok2draw) {
  833.         objc_draw(pnl, objsizs[pno], MAX_DEPTH, 0, 0, wdesk, hdesk);
  834.         objc_draw(pnl, objups[pno], MAX_DEPTH, 0, 0, wdesk, hdesk);
  835.         objc_draw(pnl, objdns[pno], MAX_DEPTH, 0, 0, wdesk, hdesk);
  836.         objc_draw(pnl, objnums[pno], MAX_DEPTH, 0, 0, wdesk, hdesk);
  837.     }
  838.  
  839.  
  840. fixleft:
  841.  
  842.     /*
  843.      * Compute and redraw 'space left' indicator and
  844.      * calculat the total partitions number */
  845.  
  846.        sizleft = disksiz;
  847.     pinfo = headptr;
  848.     tolpart = 0;
  849.     while ((pinfo->flg & P_EXISTS) && (pinfo->siz > 0))     {
  850.             sizleft -= pinfo->siz;
  851.             tolpart++;  
  852.             pinfo = pinfo->next;
  853.     }
  854.     npart = tolpart;
  855.        stuffamt(sizleft, sizstr[4]);
  856.        (pnl[SEPLEFT].ob_spec)->te_ptext = sizstr[4];
  857.  
  858.     totalpart(tolpart, sizstr[5]);
  859.        (pnl[STOLPART].ob_spec)->te_ptext = sizstr[5];
  860.  
  861.     if (ok2draw)    {
  862.         objc_draw(pnl, SEPLEFT, MAX_DEPTH, 0, 0, wdesk, hdesk);
  863.         objc_draw(pnl, STOLPART, MAX_DEPTH, 0, 0, wdesk, hdesk);
  864.     }
  865. }
  866.  
  867. /*
  868.  * Atoi `amt', #blocks, into 999.9Mb (or something like that);
  869.  * assumes enough space in `str'.
  870.  */
  871. stuffamt(amt, str)
  872. long amt;
  873. char *str;
  874. {
  875.     long mb, frac;
  876.  
  877.     mb = amt / 2048;
  878.     frac = amt - (2048 * mb);
  879.     if (frac / 16)
  880.         frac /= 205;        /* that's MEGABYTE / 10 */
  881.     else frac = 0;
  882.     if (frac < 0) frac = -frac;
  883.     if (mb < 0) mb = frac = 0;
  884.  
  885.     if (mb > 999)     {
  886.         *str++ = (mb / 1000) + '0';
  887.         mb -= 1000 * (mb / 1000);
  888.         if ((!mb) || (mb < 10))    { /* take care mb=1000 or 1001 case */
  889.             *str++ = '0';
  890.             *str++ = '0';
  891.         } else if (mb < 100)    { /* take care mb=1099 case */
  892.             *str++ = '0';
  893.         }
  894.     }
  895.     if (mb > 99) {
  896.         *str++ = (mb / 100) + '0';
  897.         mb -= 100 * (mb / 100);
  898.         if ((!mb) || (mb < 10))    {    /* take care mb=100 or 101 cases */
  899.             *str++ = '0';
  900.         }
  901.     }
  902.     if (mb > 9) {
  903.         *str++ = (mb / 10) + '0';
  904.         mb -= 10 * (mb / 10);
  905.     }
  906.     *str++ = mb + '0';
  907.  
  908.     if (frac) {
  909.         *str++ = '.';
  910.         *str++ = frac + '0';
  911.     }
  912.     *str++ = 'M';
  913.     *str++ = 'b';
  914.     *str++ = '\0';
  915. }
  916.  
  917.  
  918. /*
  919.  * Partitin button number-to-object translation table.
  920.  */
  921.  
  922. int ppart[] = {
  923.     PPART0, PPART1, PPART2, PPART3,
  924.     PPART4, PPART5, PPART6, PPART7,
  925.     PPART8, PPART9, PPART10, PPART11,
  926.     PPART12, PPART13, PPART14
  927. };
  928.  
  929. /*
  930.  * Throw up menu of canned partitions;
  931.  *    Return PPOK on [OK],
  932.  *         PPCN on [CANCEL],
  933.  *         PPEDIT on [EDIT==>],
  934.  *         ERROR on some error.
  935.  *    if `flag' < 0, this is the first time 
  936.  *    putting up the menu.
  937.  */
  938.  
  939. spartmenu()
  940. {
  941.     int i, but, tem;
  942.     char *s, *pnam, pr_id[10];
  943.  
  944.     /* Figure out partition scheme id */
  945.     /*
  946.     figprid(disksiz, pr_id);
  947.     */
  948.     
  949.     if (menuflg < 0) {
  950.         menuflg = 1;
  951.        
  952.         setschm(disksiz, partnames);
  953.         /*
  954.         if (ttscsi)    {
  955.             setschm(disksiz, partnames);
  956.         } else     {
  957.             Get all available partition schemes from wincap 'ID' entries 
  958.             wallents(partnames, pr_id);
  959.         }
  960.         */
  961.     }
  962.  
  963.     for (i = 0, s = partnames; i < 15 && *s; ++i) {
  964.         p[ppart[i]].ob_type = G_BUTTON;
  965.     p[ppart[i]].ob_spec = (long)s;
  966.     p[ppart[i]].ob_state = NORMAL;
  967.     p[ppart[i]].ob_flags = SELECTABLE | RBUTTON;
  968.     while (*s++)
  969.         ;
  970.     }
  971.  
  972.     /* rest of buttons are invisible and untouchable */
  973.     for (; i < 15; ++i) {
  974.         p[ppart[i]].ob_type = G_IBOX;
  975.     p[ppart[i]].ob_spec = 0L;            /* no thickness */
  976.     p[ppart[i]].ob_state = DISABLED;        /* nobody home */
  977.     p[ppart[i]].ob_flags = NONE;            /* disabled */
  978.     }
  979.  
  980.     /* clean up rest of the form and throw it up */
  981.     p[PPOK].ob_state = NORMAL;
  982.     p[PPCN].ob_state = NORMAL;
  983.     p[PPEDIT].ob_state = NORMAL;
  984.     
  985.     if((but = execform(p)) == PPCN || but == PPEDIT)
  986.     return;
  987.  
  988.     /* search for partition they picked */
  989.     pnlflg = 0;                /* partition scheme from menu */
  990.     for (i = 0; i < 15; ++i)
  991.     if (p[ppart[i]].ob_state & SELECTED)
  992.         break;
  993.     if (i >= 15) return but;        /* nothing changed */
  994.     pnam = p[ppart[i]].ob_spec;
  995.  
  996.     /*
  997.     if (!ttscsi)    {
  998.         i = wgetent(pnam, pr_id);                ; (floppy access) 
  999.         if (i != OK) {
  1000.             nopart[NOSCHPOK].ob_state = NORMAL;
  1001.                (nopart[NOSCHPR].ob_spec)->te_ptext = p[ppart[i]].ob_spec;
  1002.             execform(nopart);
  1003.             return ERROR;
  1004.         }
  1005.     }
  1006.     */
  1007.     npart = 4;
  1008.     ext = NO_EXT;        /* set no extended partition */
  1009.     if (headptr > 0)    free(headptr);
  1010.     if ((pinfo = (PART *)Malloc((long)sizeof(PART)*npart)) <= 0)        {
  1011.         err(nomemory);
  1012.         if (pinfo > 0)    Mfree(pinfo);
  1013.         return ERROR;
  1014.     }
  1015.     inipart(&pinfo[0], npart);        /* initialized the 'pinfo' */
  1016.     npart = 0;
  1017.     msetpart(pinfo, pnam, disksiz);
  1018.     /*
  1019.     if (ttscsi)        {
  1020.         msetpart(pinfo, pnam, disksiz);
  1021.     } else {
  1022.         for (i = 0; i < 4; ++i)
  1023.             fillpart(i, &pinfo[i]);
  1024.     }
  1025.     */
  1026.     return but;
  1027. }
  1028.  
  1029.  
  1030. /* 
  1031.  * conver the partition number for the dialog box to the string .
  1032.  *
  1033.  */
  1034.  
  1035. stpartnum(num, str)
  1036.  
  1037. int num;
  1038. char *str;
  1039.  
  1040. {
  1041.     int  i = 0;
  1042.     char tem[100];
  1043.  
  1044.     /* set the partition number header */
  1045.     *str++ = '#';
  1046.     /* conver the integer to ASCII */
  1047.     do    {    /* generate digits in reverse order */
  1048.         tem[i++] = num % 10 + '0';    /* get next digits */
  1049.     } while ((num /= 10) > 0);        /* delete it */
  1050.  
  1051.     for (; i > 0; )    { /* reverse string 'str' in place */
  1052.         *str++ = tem[--i];
  1053.     }
  1054.        *str = '\0';
  1055. }
  1056.  
  1057.  
  1058.  
  1059. /*
  1060.  *  Place partition headers at the appropiate sectors.
  1061.  *    Input:
  1062.  *        pdev - physical device partitions belong to.
  1063.  *        part - partition structure containing the partitions'
  1064.  *               information.
  1065.  *    Return:
  1066.  *        OK - if everything is fine.
  1067.  *        ERROR - error occurs when testing header sectors.
  1068.  *    Comments:
  1069.  *        Making sure that the headers occupy consecutive good 
  1070.  *    sectors.  If necessary, sizes of partitions are adjusted to 
  1071.  *    achieve the above.
  1072.  *        If any size adjustment make a partition bigger than
  1073.  *    the maximum size, the partition will be adjusted to the maximum
  1074.  *    size leaving the excessive sectors wasted.
  1075.  */
  1076.  
  1077. spheader(pdev, part)
  1078.  
  1079. int pdev;    /* physical device number */
  1080. PART *part;    /* partition info */
  1081.  
  1082. {
  1083.     /* Maximum sizes for FAT, root directory and header <in sectors> */
  1084.     long  maxdent;        /* max num entries in root dir */
  1085.     long  start;        /* starting sector number of a partition */
  1086.     long  entries, nument();
  1087.     long  movehdr, temstart, moved, psiz;
  1088.     UWORD maxfsiz, maxdsiz, hdrsiz;
  1089.     long currbsiz;        /* size of BSL b4 pheader is executed */
  1090.     int  pno;            /* partition being dealt with */
  1091.     int  done;            /* tell if location of header is found */
  1092.     int  curr;            /* current sector of header being checked */
  1093.     int  ret;            /* return code from testing header sectors */
  1094.     int     spc;            /* sectors per cluster */
  1095.     int  kindfat;       /* 12 bits fat or 16 bits fat */
  1096.     int  step;            /* the index for check the partitions */
  1097.     long bigsect(), nsect;
  1098.     long stbigsect();
  1099.     long temsect, remain;
  1100.     long cell();
  1101.     
  1102.     
  1103.     /* get the BSL ready ofr later */
  1104.     entries = nument(MEDIA);
  1105.     sortbsl(entries);
  1106.     currbsiz = bslsiz;
  1107.  
  1108.     /* Determine actual sizes and starting sectors for all partitions */
  1109.     for (pno = 0; pno < npart; pno++) {
  1110.         
  1111.         /* Partition 0 starts right after root sect.  The rest starts right
  1112.            after its previous partition ???*/
  1113.         if (pno == 0)
  1114.             start = 1 + currbsiz; 
  1115.         else if (pno == 4)
  1116.             start = part[ext].p_st;    /* start in extened partition */
  1117.         else
  1118.             start = part[pno-1].p_st + part[pno-1].p_siz;
  1119.         
  1120.         /* Check if partition exists.  If it doesn't, move on to next one */
  1121.         if ((!(part[pno].p_flg & P_EXISTS)) || (pno == ext)) {
  1122.             part[pno].p_st = start;
  1123.             continue;
  1124.         }
  1125.         if (pno > 3)     {
  1126.             psiz = part[pno].p_siz - ROOTSECT;
  1127.         } else    {
  1128.             psiz = part[pno].p_siz;
  1129.         }
  1130.  
  1131.         /* estimate the bps */
  1132.         /* MAXSECT = 16MB - 8 */
  1133.         bps = cell((psiz-7)*BPS, (long)MAXSECT);
  1134.         /* the real pbs */
  1135.         bps = BPS * n2power((UWORD)cell(bps, (long)BPS));
  1136.         ratio = bps / BPS;
  1137.         nsect = psiz / ratio;
  1138.  
  1139.         /* Detail of calculations in part.c dopart() */
  1140.         /* find max FAT size. FAT16: 16 bits fat; FAT12: 12bits fat */
  1141.         maxfsiz = ((((nsect / SPC) + 2)*2) / bps) + 1;
  1142.         /* find max root dir entries */
  1143.         if (nsect < 0x5000L)    maxdent = NUMEN;
  1144.         else maxdent = nsect / 80;
  1145.         maxdent = (maxdent + (bps/BPDIR -1)) & ~(bps/BPDIR -1);
  1146.         /* find max root dir size */
  1147.         maxdsiz = (maxdent * BPDIR) / bps + 1;
  1148.  
  1149.            if (pno > 3)    {  /* they are extended partitions */
  1150.         /*-------------------------------------------------------*
  1151.          * Biggest possible header for a extended partition <in sectors> 
  1152.          *    =  Root sector + Boot Sector + 2 FATs + Root Dir    
  1153.          *-------------------------------------------------------*/
  1154.          /* convert it back to 512 bps size */
  1155.             hdrsiz = 1 + ratio + ((maxfsiz * 2) + maxdsiz) * ratio;
  1156.         } else
  1157.         /*-------------------------------------------------------*
  1158.          * Biggest possible header for a partition <in sectors>  *
  1159.          *    =  Boot Sector + 2 FATs + Root Dir         *
  1160.          *-------------------------------------------------------*/
  1161.          /* convert it back to 512 bps size */
  1162.             hdrsiz = (1 + (maxfsiz * 2) + maxdsiz) * ratio;
  1163.     
  1164.     /*-----------------------------------------------------------------*
  1165.      * Look for a chunk of sectors starting at "start" (or after, but  *
  1166.      * as close as possible) which is big enough to hold the biggest   *
  1167.      * possible header.                           *
  1168.      *-----------------------------------------------------------------*/
  1169.     done = 0;       /* assume correct location not found yet */
  1170.     moved = 0;
  1171.     while (!done) {
  1172.         /*----------------------------------------------------------*
  1173.          * Find out if header contains any bad sectors by checking    *
  1174.          * range of sectors to be occupied by the header against    *
  1175.          * the BSL.                                                    *
  1176.          *----------------------------------------------------------*/
  1177.         for (curr = 0; curr < hdrsiz; curr++)    {
  1178.             if (srchbsl(start+curr, entries) == YES)
  1179.                 break;
  1180.         }
  1181.         if (curr < hdrsiz)    {    /* bad sector found in header */
  1182.             /* move header to start after the bad sector */
  1183.             moved += curr + 1;
  1184.             start += curr + 1;
  1185.         } else {
  1186.                if ((ret = testhdr(pdev, start, hdrsiz)) < 0)
  1187.                  return ERROR;
  1188.             if (ret)    {    /* some bad sectors found in header */
  1189.                 entries = nument(MEDIA);
  1190.                 sortbsl(entries);
  1191.             } else {        /* all sectors belong ot header are good */
  1192.                 done = 1;
  1193.             }
  1194.         }
  1195.     }
  1196.     
  1197.     if (moved) {    /* header has been moved */
  1198.         /*-------------------------------------------------------*
  1199.          * Expand previous partition (except if the current one  *
  1200.          * is partition 0, then there is no previous partition), *
  1201.          * and enforce maximum partition size on it.         *
  1202.          *-------------------------------------------------------*/
  1203.         if (ratio > 1)    {    /* big sector */
  1204.             start -= moved;
  1205.             moved = stbigsect(moved);
  1206.             start += moved;
  1207.         }
  1208.         if (pno > 0) {
  1209.             if (part[pno-1].p_siz + moved > disksiz)
  1210.                 part[pno-1].p_siz = disksiz;
  1211.             else
  1212.                 part[pno-1].p_siz += moved;
  1213.         }
  1214.             
  1215.         /* Shrink size of current partition */
  1216.         part[pno].p_siz -= moved;
  1217.     } 
  1218.  
  1219.     /* Where current partition should start */
  1220.     part[pno].p_st = start;
  1221.  
  1222.     /* add the waist sectors of big partition to the next partition */
  1223.     /* partition #3 in the pinfo is the last partition */
  1224.     /* partition # npart-1 in the pinfo is the last partition in 
  1225.         the extended partition */
  1226.     if ((pno != 3) && (pno != npart - 1) && 
  1227.                     (part[pno].p_siz >= MB16))        { /* big partition */
  1228.         temsect = part[pno].p_siz;
  1229.         if (pno > 3)    { /* extended big partition */
  1230.            part[pno].p_siz = ROOTSECT + bigsect(part[pno].p_siz-ROOTSECT);
  1231.         } else {    /* prime big partition */
  1232.            part[pno].p_siz = bigsect(part[pno].p_siz);
  1233.         }
  1234.         remain = temsect - part[pno].p_siz;
  1235.         if (remain)    {
  1236.             part[pno+1].p_siz += remain;
  1237.             part[pno+1].p_st -= remain;
  1238.         }
  1239.     }
  1240.  
  1241.   }
  1242.     /* last existing partition has to sacrifice some space for the BSL    */
  1243.     /* and the root sector of device.                    */
  1244.     if ((ext == 3) || ((!(part[2].p_flg & P_EXISTS)) &&
  1245.                         (!(part[3].p_flg & P_EXISTS))))    { 
  1246.         /* the last partition is inside the extended partitions */
  1247.         step = npart;
  1248.         /* the total extended partition should not inculde the bad sector */
  1249.         /* list and root sector */
  1250.         part[ext].p_siz -= (currbsiz + 1);
  1251.     } else {    /* the last partition is in the prime partitions */
  1252.         step = NPARTS;
  1253.     }
  1254.     for (pno = step-1; pno >= 0; pno--) {
  1255.         if (part[pno].p_flg & P_EXISTS) {
  1256.             part[pno].p_siz -= (currbsiz + 1);
  1257.             break;
  1258.         }
  1259.     }
  1260.  
  1261.     /* have to move partitions (existing or not) which start
  1262.        right after the BSL if BSL has been expanded  */
  1263.     if (bslsiz > currbsiz) {        /* BSL becomes bigger? */
  1264.         for (pno = 0; pno < NPARTS; pno++) {
  1265.             if (part[pno].p_st == currbsiz + 1) {
  1266.                 part[pno].p_st = bslsiz + 1;
  1267.                 if (part[pno].p_siz > 0)
  1268.                     part[pno].p_siz -= (bslsiz - currbsiz);
  1269.             }
  1270.         }
  1271.     }
  1272.   return OK;    /* everything is fine */
  1273. }
  1274.  
  1275.  
  1276. long stbigsect(amt)
  1277. long amt;
  1278.  
  1279. {
  1280.     long numsect;
  1281.     if (ratio > 1)    {
  1282.         numsect = (amt % ratio) ? (amt / ratio + 1) : (amt /ratio);
  1283.         return(numsect * ratio);
  1284.     } else {
  1285.         return(amt);
  1286.     }
  1287. }
  1288.  
  1289.  
  1290. long bigsect(amt)
  1291. long amt;
  1292.  
  1293. {
  1294.     if (ratio > 1)    {
  1295.         return((amt / ratio) * ratio);
  1296.     } else {
  1297.         return(amt);
  1298.     }
  1299. }
  1300.  
  1301. /* 
  1302.  * Given size of a hard disk, figure out
  1303.  * the partition scheme ID to look for.
  1304.  * ID is 2 or more characters long.
  1305.  */
  1306. figprid(hdsiz, pr_id)
  1307. long hdsiz;
  1308. char pr_id[];
  1309. {
  1310.     UWORD mega, over;
  1311.     char numbuf[10];
  1312.     
  1313.     /* Round off disk size in megabytes */    
  1314.     mega = hdsiz / MEGABYTE;
  1315.     
  1316.     /* Round off disk size to nearest 10Mb */
  1317.     /*
  1318.     over = mega % 10;
  1319.     if (over >= 5)
  1320.        mega += (10 - over);
  1321.     else
  1322.        mega -= over;
  1323.     */
  1324.     itoa(mega, numbuf);
  1325.     strcpy(pr_id, numbuf);
  1326. }
  1327.  
  1328.  
  1329.  
  1330. /*
  1331.  * Check if partition scheme selected is _legal_.
  1332.  * _Legal_ means the scheme does not map to non-existing memory.
  1333.  * If it is not, prompt user to pick partition again.
  1334.  *    Input:
  1335.  *        pdev - physical unit we're trying to partition.
  1336.  *        xpinfo - partition block user selected.
  1337.  *    Return:
  1338.  *        OK - if partition scheme is _legal_.
  1339.  *        ERROR - if partition scheme is illegal.
  1340.  */
  1341.  
  1342. chkpart(pdev, xpinfo)
  1343. int pdev;
  1344. PART *xpinfo;
  1345. {
  1346.     char bs[512];
  1347.     SECTOR totsiz;
  1348.     int     i, ret;
  1349.     
  1350.     
  1351.     /* Get partition information from disk's root block.*/
  1352.     if ((ret = getroot(pdev, bs, (SECTOR)0)) != 0) {
  1353.         if (tsterr(ret) != OK)
  1354.             err(rootread);
  1355.         return (1);        /* return error but it is not a size too big */
  1356.     }
  1357.  
  1358.     disksiz = ((RSECT *)(bs + 0x200 - sizeof(RSECT)))->hd_siz;
  1359.     totsiz = 0;
  1360.     for (i = 0; i < NPARTS; i++) {
  1361.         if (xpinfo[i].p_flg & P_EXISTS)    {
  1362.             totsiz += xpinfo[i].p_siz;
  1363.         }
  1364.         if (totsiz > disksiz)
  1365.             return ERROR;     /* size too big */
  1366.     }
  1367.     return OK;
  1368. }
  1369.     
  1370.  
  1371.  
  1372. /*
  1373.  *  Make sure that sectors assigned to a partition header are GOOD.
  1374.  *    Input:
  1375.  *        pdev - physical device number partition belongs to.
  1376.  *        start - starting (physical) sector number header starts.
  1377.  *        hdrsiz - number of sectors header occupies.
  1378.  *    Return:
  1379.  *        OK - if all sectors in header are good.
  1380.  *        positive number - if entries are added to BSL in testing
  1381.  *                    the header.
  1382.  *        ERROR - if somewhere the process went wrong.
  1383.  *    Comments:
  1384.  *        Bad Sectors found are added as USER bad sectors.  
  1385.  *    First, because we can't expand the VENDOR list while preserving
  1386.  *    the USER list.  Second, this is ok, because even if the USER list
  1387.  *    is full, the user should reformat the disk anyway, and if the
  1388.  *    sector is REALLY bad, it would be discovered again then.
  1389.  */
  1390. testhdr(pdev, start, hdrsiz)
  1391. int pdev;
  1392. SECTOR start;
  1393. UWORD hdrsiz;
  1394. {
  1395.     long size, pattern;
  1396.     extern long longrandom();
  1397.     extern int tformat;        /* flag */
  1398.     UWORD sectcnt, list;
  1399.     int ret, nbad, clean=1;
  1400.     SECTOR sect;
  1401.     char *buf;        /* buffer with test data */
  1402.     
  1403.     size = (long)hdrsiz << 9;
  1404.     if ((buf = (char *)Malloc(size)) <= 0) {
  1405.         err(nomemory);
  1406.         ret = NOMEM;
  1407.         goto wrapup;
  1408.     }
  1409.         
  1410.     /*
  1411.      * Try to write to header's sectors.
  1412.      */
  1413.     pattern = longrandom();
  1414.     fillbuf(buf, size, pattern);
  1415.     sectcnt = hdrsiz;
  1416.     sect = start;
  1417.     nbad = 0;
  1418.  
  1419.     if ((ret = wrsects(pdev, sectcnt, buf, sect)) != 0) {
  1420.         if (tsterr(ret) == OK) {
  1421.             ret = ERROR;
  1422.             goto wrapup;
  1423.         }
  1424.         clean = 0;
  1425.         
  1426.         while (sectcnt) {    /* find out which sector is indeed bad */
  1427.         if ((ret = wrsects(pdev, 1, 0L, sect)) != 0) {
  1428.             if (tsterr(ret) == OK) {
  1429.                 ret = ERROR;
  1430.                 goto wrapup;
  1431.             }
  1432.             if (sect < 3) {
  1433.                 ret = err(rsrvbad);
  1434.                 goto wrapup;
  1435.             }
  1436.                     
  1437.                  badbuf[nbad++] = sect;    /* store bad sector num */
  1438.                     
  1439.                 /* buffer is filled up, have to add bad sectors
  1440.                    found so far to the BSL before continuing.   */
  1441.                 if (nbad == WARNBADSECTS) {
  1442.                     /* Decide which list to add to */
  1443.                     if (tformat == TRUE)
  1444.                         list = VENDOR;
  1445.                     else list = USER;
  1446.                        if ((ret=addbsl(pdev, list, nbad)) < 0) {
  1447.                            ret = err(rsrvbad);
  1448.                            goto wrapup;
  1449.                        }
  1450.                        nbad = 0;    /* start counting again */
  1451.                 }
  1452.             }
  1453.             sect++;
  1454.             sectcnt--;
  1455.         }
  1456.         if (nbad) {    /* there are bad sectors found not added to BSL yet */
  1457.             /* Decide which list to add to */
  1458.             if (tformat == TRUE)
  1459.                 list = VENDOR;
  1460.             else list = USER;
  1461.             if ((ret = addbsl(pdev, list, nbad)) < 0) {
  1462.                 ret = ERROR;
  1463.                 goto wrapup; 
  1464.             }
  1465.             nbad = 0;
  1466.         }
  1467.     }
  1468.     
  1469.     /* Try to read header's sectors */
  1470.     sectcnt = hdrsiz;
  1471.     sect = start;
  1472.     nbad = 0;
  1473.     if ((ret = rdsects(pdev, sectcnt, buf, sect)) != 0) {
  1474.         if (tsterr(ret) == OK) {
  1475.             ret = ERROR;
  1476.             goto wrapup;
  1477.         }
  1478.         clean = 0;
  1479.         
  1480.         while (sectcnt) {    /* find out which sector is indeed bad */
  1481.         if ((ret = rdsects(pdev, 1, buf, sect)) != 0) {
  1482.             if (tsterr(ret) == OK) {
  1483.                 ret = ERROR;
  1484.                 goto wrapup;
  1485.             }
  1486.                 if (sect < 3) {
  1487.             ret = err(rsrvbad);
  1488.             goto wrapup;
  1489.         }
  1490.                     
  1491.                  badbuf[nbad++] = sect;    /* store bad sector num */
  1492.                     
  1493.                 /* buffer is filled up, have to add bad sectors
  1494.                    found so far to the BSL before continuing.   */
  1495.                 if (nbad == WARNBADSECTS) {
  1496.                     /* Decide which list to add to */
  1497.                     if (tformat == TRUE)
  1498.                     list = VENDOR;
  1499.                     else list = USER;
  1500.                        if ((ret = addbsl(pdev, list, nbad)) < 0) {
  1501.                            ret = ERROR;
  1502.                            goto wrapup;
  1503.                        }
  1504.                        nbad = 0;    /* start counting again */
  1505.                 }
  1506.             }
  1507.             sect++;
  1508.             sectcnt--;
  1509.         }
  1510.         if (nbad) {    /* there are bad sectors found not added to BSL yet */
  1511.             /* Decide which list to add to */
  1512.             if (tformat == TRUE)
  1513.                 list = VENDOR;
  1514.             else list = USER;
  1515.             if ((ret = addbsl(pdev, list, nbad)) < 0) {
  1516.                 ret = ERROR;
  1517.                 goto wrapup; 
  1518.             }
  1519.             nbad = 0;
  1520.         }
  1521.     }
  1522. wrapup:
  1523.     if (buf > 0)  Mfree((long)buf);
  1524.     
  1525.     if (ret < 0)
  1526.         return ret;
  1527.         
  1528.     if (!clean) {
  1529.         /* write new bsl back to disk */
  1530.         if (wrbsl(pdev) != OK) {
  1531.             return ERROR;
  1532.         }
  1533.         return 1;
  1534.     }
  1535.         
  1536.     return OK;
  1537. }
  1538.  
  1539. long
  1540. cell(top, bottom)
  1541. long top;
  1542. long bottom;
  1543. {
  1544.     return ((top % bottom) ? (top / bottom + 1) :
  1545.             (top / bottom));
  1546. }
  1547.  
  1548.  
  1549. n2power(num)
  1550. UWORD num;
  1551. {
  1552.     UWORD power = 1;
  1553.  
  1554.     for (;;)    {
  1555.         if (num <= power )    {
  1556.             return (power);
  1557.         }
  1558.         power <<= 1;
  1559.     } 
  1560. }
  1561.  
  1562.  
  1563. DPART
  1564. *addr(index)
  1565. int index;
  1566. {
  1567.     DPART *temptr;
  1568.     int i;
  1569.  
  1570.     if (index < 0)    return nill;
  1571.     if (!index) return (headptr);
  1572.     temptr = headptr->next;
  1573.     for (i = 1; i < index; i++)    {
  1574.         temptr = temptr->next;
  1575.     }
  1576.     return (temptr);
  1577. }
  1578.  
  1579. DPART
  1580. *last()
  1581. {
  1582.     DPART *temptr;
  1583.     int i;
  1584.  
  1585.     if (!headptr) return (headptr);
  1586.     temptr = headptr;
  1587.     while (temptr->next)
  1588.         temptr = temptr->next;
  1589.     return (temptr);
  1590. }
  1591.  
  1592.  
  1593.  
  1594. creatmem(num)
  1595. int num;        /* number of block to malloc */
  1596. {
  1597.     DPART *temptr;
  1598.     DPART *last();
  1599.     int i;
  1600.  
  1601.     if (headptr == nill)    {
  1602.         if ((headptr = (DPART *)mymalloc((int)sizeof(DPART))) <= 0)    {;
  1603.             err(nomemory);
  1604.             if (headptr > 0) free(headptr);
  1605.             return ERROR;
  1606.         }
  1607.         headptr->next = nill;
  1608.         headptr->siz = 0L;
  1609.         headptr->flg = 0;
  1610.     }
  1611.     temptr = last();
  1612.     for (i = 0; i < num; i++)    {
  1613.         if ((temptr->next = (DPART *)mymalloc((int)sizeof(DPART))) <= 0)    {
  1614.             err(nomemory);
  1615.             if (headptr > 0) free(headptr);
  1616.             return ERROR;
  1617.  
  1618.         }
  1619.         temptr = temptr->next;
  1620.         temptr->next = nill;
  1621.         temptr->siz = 0L;
  1622.         temptr->flg = 0;
  1623.     }
  1624. }
  1625.  
  1626.  
  1627. dpart2part(extpart)
  1628. int extpart ;    /* set the extended pointer in the 4th place */
  1629. {
  1630.     int i;
  1631.     DPART *temptr;
  1632.  
  1633.     /* if npart > 4; need 1 more space for the extended partition */
  1634.     if (npart > 4)    {
  1635.         i = npart - extend;    /* the index that extended form the end of part. */
  1636.         npart += NPARTS-extpart;    /* add 1 extra space for the extended */
  1637.                                     /* partition and 0 or 1 or 2 space for */
  1638.                                     /* the prime partition in the root */
  1639.         extend = npart - i;    /* move 2 space for 2 prime partition in the root */
  1640.     } else {                /* set the extpart to -1 */
  1641.         npart = 4;
  1642.         extpart = -1;
  1643.         ext = NO_EXT;
  1644.     }
  1645.     if ((pinfo = (PART *)Malloc((long)sizeof(PART)*npart)) <= 0)    {
  1646.         err(nomemory);
  1647.         if (pinfo > 0) Mfree(pinfo);
  1648.         free(headptr);
  1649.         return ERROR;
  1650.     }
  1651.     inipart(pinfo, npart);  
  1652.     temptr = headptr;
  1653.     for (i = 0; i < npart; i++)        {
  1654.         if (!(temptr->flg & P_EXISTS)) {
  1655.             if (sizleft > 0) {
  1656.                 if (temptr->siz > sizleft) {
  1657.                     pinfo[i].p_siz = sizleft;
  1658.                 }
  1659.                 sizleft -= temptr->siz;
  1660.             }
  1661.         } else {
  1662.             pinfo[i].p_siz = temptr->siz;
  1663.             pinfo[i].p_flg = P_EXISTS;
  1664.             if (i == extpart)    {
  1665.                 pinfo[i].p_id[0] = 'X';
  1666.                 pinfo[i].p_id[1] = 'G';
  1667.                 pinfo[i].p_id[2] = 'M';
  1668.                 pinfo[i].p_siz = 0L;
  1669.             } else if ((extpart == 1) && ((i == 2) || (i==3)))    {
  1670.                 pinfo[i].p_flg = 0;
  1671.                 pinfo[i].p_siz = 0L;
  1672.             } else if ((extpart == 2) && (i==3))    {
  1673.                 pinfo[i].p_flg = 0;
  1674.                 pinfo[i].p_siz = 0L;
  1675.             } else if (temptr->siz < MB16)    {
  1676.                 pinfo[i].p_id[0] = 'G';
  1677.                 pinfo[i].p_id[1] = 'E';
  1678.                 pinfo[i].p_id[2] = 'M';
  1679.                 temptr = temptr->next;
  1680.             } else {
  1681.                 pinfo[i].p_id[0] = 'B';
  1682.                 pinfo[i].p_id[1] = 'G';
  1683.                 pinfo[i].p_id[2] = 'M';
  1684.                 temptr = temptr->next;
  1685.             }
  1686.         }
  1687.     }
  1688.     free(headptr);
  1689.     if (extpart != NO_EXT)    {
  1690.         asmpart(extpart);
  1691.     }
  1692.     return OK;
  1693. }
  1694.  
  1695.  
  1696. asmpart(extpart)
  1697. int extpart ;    /* the extended partition pointer */
  1698. {
  1699.     int i;
  1700.  
  1701.     /* # of extened partition to add up */
  1702.     for (i = 4; i < extend; i++)        {
  1703.         pinfo[extpart].p_siz += pinfo[i].p_siz;
  1704.     }
  1705.     if (extpart == 3)    {
  1706.         return OK;        /* done */
  1707.     } else     {
  1708.         /* put the last (npart-extend-1) partitions to */
  1709.         /* the 3rd or 4th place as prime partitions */
  1710.         i = extend;
  1711.         if (i < npart)    {
  1712.             pinfo[extpart+1].p_siz = pinfo[i].p_siz;
  1713.             pinfo[extpart+1].p_flg = P_EXISTS;
  1714.             if (pinfo[extpart+1].p_siz < MB16)    {
  1715.                 pinfo[extpart+1].p_id[0] = 'G';
  1716.                 pinfo[extpart+1].p_id[1] = 'E';
  1717.                 pinfo[extpart+1].p_id[2] = 'M';
  1718.             } else {
  1719.                 pinfo[extpart+1].p_id[0] = 'B';
  1720.                 pinfo[extpart+1].p_id[1] = 'G';
  1721.                 pinfo[extpart+1].p_id[2] = 'M';
  1722.             }
  1723.             pinfo[i].p_flg = 0;
  1724.             pinfo[i].p_siz = 0L;
  1725.             pinfo[i].p_id[0] = '0';
  1726.             pinfo[i].p_id[1] = '0';
  1727.             pinfo[i].p_id[2] = '0';
  1728.             npart--;
  1729.         } 
  1730.         if (i++ < npart)    {
  1731.             pinfo[extpart+2].p_siz = pinfo[i].p_siz;
  1732.             pinfo[extpart+2].p_flg = P_EXISTS;
  1733.             if (pinfo[extpart+2].p_siz < MB16)    {
  1734.                 pinfo[extpart+2].p_id[0] = 'G';
  1735.                 pinfo[extpart+2].p_id[1] = 'E';
  1736.                 pinfo[extpart+2].p_id[2] = 'M';
  1737.             } else {
  1738.                 pinfo[extpart+2].p_id[0] = 'B';
  1739.                 pinfo[extpart+2].p_id[1] = 'G';
  1740.                 pinfo[extpart+2].p_id[2] = 'M';
  1741.             }
  1742.             pinfo[i].p_flg = 0;
  1743.             pinfo[i].p_siz = 0L;
  1744.             pinfo[i].p_id[0] = '0';
  1745.             pinfo[i].p_id[1] = '0';
  1746.             pinfo[i].p_id[2] = '0';
  1747.             npart--;
  1748.         }
  1749.     }
  1750. }
  1751.  
  1752.  
  1753. part2dpart(numpart)
  1754. int numpart;
  1755. {
  1756.  
  1757.     int i;
  1758.     DPART *temptr;
  1759.  
  1760.     headptr = nill;
  1761.     if (creatmem(numpart) == ERROR) {
  1762.         return ERROR;
  1763.     }
  1764.     temptr = headptr;
  1765.     for (i = 0; i < numpart; i++) {
  1766.         if (pinfo[i].p_flg & P_EXISTS)    {
  1767.             temptr->siz = pinfo[i].p_siz;
  1768.             temptr->flg = P_EXISTS;
  1769.         } 
  1770.         temptr = temptr->next;
  1771.     }
  1772. }
  1773.